<template>
  <el-form label-width="120px" :model="spuInfo" :rules="rules" ref="formRef">
    <el-form-item label="SPU名称" prop="spuName">
      <el-input placeholder="SPU名称" v-model="spuInfo.spuName" />
    </el-form-item>
    <el-form-item label="品牌" prop="tmId">
      <el-select placeholder="请选择" v-model="spuInfo.tmId">
        <el-option
          :label="item.tmName"
          :value="item.id!"
          v-for="item in trademarkList"
          :key="item.id" />
      </el-select>
    </el-form-item>
    <el-form-item label="SPU描述" prop="description">
      <el-input
        type="textarea"
        rows="4"
        v-model="spuInfo.description"
        placeholder="SPU描述" />
    </el-form-item>
    <el-form-item label="SPU图片" prop="spuImageList">
      <el-upload
        v-model:file-list="(spuInfo.spuImageList as any)"
        :action="`${VITE_BASE_URL}/admin/product/fileUpload`"
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
        :on-success="handleSuccess">
        <el-icon><Plus /></el-icon>
      </el-upload>

      <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" />
      </el-dialog>
    </el-form-item>
    <el-form-item label="SPU销售属性" prop="spuSaleAttrList">
      <div>
        <el-select :placeholder="selectText" v-model="ValueIdValueName">
          <el-option
            :label="item.name"
            :value="item.id + ':' + item.name"
            :key="item.id"
            v-for="item in restSaleAttrList" />
        </el-select>
        <el-button
          type="primary"
          :icon="Plus"
          :disabled="!ValueIdValueName"
          @click="addSpuSaleAttr">
          添加销售属性
        </el-button>
      </div>

      <el-table :data="spuInfo.spuSaleAttrList" style="margin-top: 10px">
        <el-table-column
          label="序号"
          type="index"
          width="80px"
          align="center"></el-table-column>
        <el-table-column
          prop="saleAttrName"
          label="属性名"
          width="140px"></el-table-column>
        <el-table-column label="属性值名称列表">
          <template v-slot="{ row, $index }">
            <el-tag
              type="success"
              v-for="(value, index) in row.spuSaleAttrValueList"
              :key="value.id"
              style="margin-right: 5px"
              closable
              @close="row.spuSaleAttrValueList.splice(index, 1)">
              {{ value.saleAttrValueName }}
            </el-tag>
            <el-input
              @blur="toShow(row)"
              v-if="row.isEdit"
              style="width: 100px"
              placeholder="请输入"
              ref="InputRef"
              @keyup.enter="toShow(row)"
              v-model="Valuesale"></el-input>
            <el-button
              v-else
              @click="toEdit(row)"
              size="small"
              :icon="Plus"></el-button>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="140px">
          <template v-slot="{ $index }">
            <el-button
              type="danger"
              @click="spuInfo.spuSaleAttrList.splice($index, 1)"
              :icon="Delete"></el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-form-item>

    <el-form-item>
      <el-button type="primary" @click="save" :loading="saveLoading">
        保存
      </el-button>
      <el-button @click="emit('setShowStatus', ShowStatus.SPU_LIST)">
        取消
      </el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import {
  addOrUpdateSpuApi,
  getBaseSaleAttrListApi,
  getSpuImageListApi,
  getSpuSaleAttrListApi,
} from "@/api/product/Spu";
import { cloneDeep } from "lodash";

export default defineComponent({
  name: "SpuForm",
});
</script>

<script setup lang="ts">
import type {
  BaseSaleAttrListModel,
  spuModel,
  SpuSaleAttrListModel,
  SpuSaleAttrModel,
} from "@/api/product/model/spuModel";
import type { trademarksModel } from "@/api/product/model/trademarkModel";

import { ShowStatus } from "../types";
import { reactive, ref, onMounted, computed, nextTick } from "vue";
import { Plus, Delete } from "@element-plus/icons-vue";

import {
  ElMessage,
  type FormInstance,
  type FormRules,
  type InputInstance,
  type UploadProps,
  type UploadUserFile,
} from "element-plus";

import { getAllTrademarkListApi } from "@/api/product/trademark";

// 声明定义自定义事件, 返回的是分发事件的函数
const emit = defineEmits<{
  (e: "setShowStatus", value: ShowStatus): void;
}>();

const props = defineProps<{
  spu: spuModel;
}>();

const saveLoading = ref(false);
/*
请求添加或修改spu
*/
const save = async () => {
  // 先校验
  // formRef.value?.validate((valid) => {
  //   if (valid) {
  //     alert('准备请求...')
  //   }
  // })
  // 校验的返回值是一个promise, 校验成功promise就会成功
  await formRef.value?.validate();
  // 在发请求对spuInfo进行数据整理/处理

  // 对spuInfo产生一个拷贝对象
  const cloneSpuInfo = cloneDeep(spuInfo);
  /*需要在数据类型添加: response的结构
  	给name的值添加为imgName属性
  	将imgUrl或response.data的值给imgUrl */
  cloneSpuInfo.spuImageList = cloneSpuInfo.spuImageList.map((item) => ({
    imgName: item.name!,
    imgUrl: item.response ? item.response.data : item.imgUrl,
  }));

  /* 2. 处理 spuSaleAttr对象
		删除isEdit属性
		过滤掉没有属性值名称的属性对象 */
  cloneSpuInfo.spuSaleAttrList = cloneSpuInfo.spuSaleAttrList.filter((item) => {
    // 如果有属性值, 就留下来
    if (item.spuSaleAttrValueList.length > 0) {
      // 删除isEdit属性
      delete item.isEdit;
      return true;
    }

    return false;
  });

  // 显示loading
  saveLoading.value = true;

  try {
    // 发送添加/更新的请求: addOrUpdateSpuApi
    await addOrUpdateSpuApi(cloneSpuInfo);
    // 请求成功后: 提示 / 显示列表页面
    ElMessage.success("保存成功!");
    emit("setShowStatus", ShowStatus.SPU_LIST);
    // 隐藏loading
    // saveLoading.value = false
  } catch (error) {
    // 隐藏loading
    // saveLoading.value = false
  } finally {
    // 请求成功或失败都要隐藏loading
    saveLoading.value = false;
  }
};

/* **表单校验 start** */
const formRef = ref<FormInstance>();
const rules: FormRules = {
  spuName: [{ required: true, message: "spu名称是必须的", trigger: "blur" }],
  tmId: [{ required: true, message: "品牌是必须的" }],
  description: [{ required: true, message: "描述是必须的" }],
  spuImageList: [{ required: true, message: "必须上传spu图片", type: "array" }],
  spuSaleAttrList: [
    { required: true, message: "必须指定spu销售属性", type: "array" },
  ],
};
/* **表单校验 end** */

// 获取输入框
const InputRef = ref<InputInstance>();
const Valuesale = ref("");

// 变为编辑模式
const toEdit = (row: SpuSaleAttrModel) => {
  row.isEdit = true;

  // 自动获取焦点
  nextTick(() => {
    InputRef.value?.focus();
  });
};

// 变为查看模式
const toShow = (row: SpuSaleAttrModel) => {
  // 判断是否有值
  if (Valuesale.value) {
    const notRepeat = row.spuSaleAttrValueList.some(
      (item) => item.saleAttrValueName === Valuesale.value
    );
    // 判断是否重复
    if (!notRepeat) {
      const attrValue = {
        saleAttrValueName: Valuesale.value,
        baseSaleAttrId: row.baseSaleAttrId,
      };
      row.spuSaleAttrValueList.push(attrValue);
    }
  }
  // 变为查看模式
  row.isEdit = false;
  // 清空
  Valuesale.value = "";
};

// 声明一个用于收集spu表单数据的spu详情信息对象
const spuInfo = reactive<spuModel>(props.spu);

// 所有品牌的列表
const trademarkList = ref<trademarksModel>([]);
// 所有销售属性的列表
const saleAttrList = ref<BaseSaleAttrListModel>([]);

const ValueIdValueName = ref("");
// 点击添加一个新的spu销售属性
const addSpuSaleAttr = () => {
  // 对valueIdValueName进行拆分, 得到 id和name
  const [id, name] = ValueIdValueName.value.split(":");
  // 创建一个新的spu销售属性对象, 并添加到对应的列表中
  spuInfo.spuSaleAttrList.push({
    baseSaleAttrId: +id,
    saleAttrName: name,
    spuSaleAttrValueList: [],
  });
  // 清除选择收集的valueIdValueName
  ValueIdValueName.value = "";
};

// 剩余可选的销售属性列表
const restSaleAttrList = computed(() => {
  return saleAttrList.value.filter((attr) => {
    // attr.name在spuInfo.spuSaleAttrList中有没有对应的
    return !spuInfo.spuSaleAttrList.some(
      (saleAttr) => saleAttr.saleAttrName === attr.name
    );
  });
});
// 计算出下拉列表的提示文本
const selectText = computed(() => {
  const length = restSaleAttrList.value.length;
  return length === 0 ? "没有啦!" : `还有${length}个可选的`;
});
/*
1. 获取所有品牌列表 trademark.getAllTrademarkListApi()  trademarkList
2. 获取基础销售属性列表  spu.getBaseSaleAttrListApi()  saleAttrList
3. 获取spu图片列表   spu.getSpuImageListApi(spuId)  spuInfo.spuImageList
4. 获取spu销售属性列表  spu.getSpuSaleAttrListApi(spuId)  spuInfo.spuSaleAttrList
*/
// 挂载的时候发送4个请求
onMounted(async () => {
  trademarkList.value = await getAllTrademarkListApi();
});
onMounted(async () => {
  saleAttrList.value = await getBaseSaleAttrListApi();
});
onMounted(async () => {
  if (!spuInfo.id) return;

  const SpuImageList = await getSpuImageListApi(spuInfo.id!);
  // spuInfo.spuImageList = SpuImageList;

  // spuInfo.spuImageList.forEach((item) => {
  //   item.name = item.imgName;
  //   item.url = item.imgUrl;
  // });

  spuInfo.spuImageList = SpuImageList.map((item) => ({
    ...item,
    name: item.imgName,
    url: item.imgUrl,
  }));
});
onMounted(async () => {
  if (!spuInfo.id) return;
  const SpuSaleAttrList = await getSpuSaleAttrListApi(spuInfo.id!);
  spuInfo.spuSaleAttrList = SpuSaleAttrList;
});

// 图片
const VITE_BASE_URL = import.meta.env.VITE_BASE_URL;

const dialogImageUrl = ref("");
const dialogVisible = ref(false);

// 点击删除回调
// uploadFile: 要删除的图片对象
// uploadFiles: 剩余的图片列表
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  console.log(uploadFile, uploadFiles);
  spuInfo.spuImageList = uploadFiles as any; // 数据等到发请求前进行整理
};

// 点击放大镜的回调
// uploadFile: 点击的图片对象
const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  // 指定要显示的大图url
  dialogImageUrl.value = uploadFile.url!;
  // 显示dialog
  dialogVisible.value = true;
};
// 上传成功的回调
// response: 上传请求的响应体数据  {data: 图片的url}
// uploadFile: 上传成功的图片对象
// uploadFiles: 已上传的图片列表
const handleSuccess: UploadProps["onSuccess"] = (
  response,
  uploadFile,
  uploadFiles
) => {
  console.log("onSuccess", uploadFiles);
  spuInfo.spuImageList = uploadFiles as any; // 数据等到发请求前进行整理

  // 在上传图片成功后, 手动清除错误信息
  formRef.value?.clearValidate(["spuImageList"]);
};
</script>

<style scoped lang="scss"></style>
